#include <stdexcept>

#include "os_rw_lock.h"

os_rw_lock::os_rw_lock() :
    m_reader_count(0),
    m_writer_count(0),
    m_waiting_writers(0),
    m_write_privilege(false),
    m_current_writer()
{
}

// 内部辅助方法
bool os_rw_lock::can_acquire_read_lock() const
{
    return m_writer_count == 0 && !m_write_privilege;
}

bool os_rw_lock::can_acquire_write_lock() const
{
    return m_reader_count == 0 && m_writer_count == 0;
}

void os_rw_lock::acquire_read_lock_internal(std::thread::id thread_id)
{
    m_reader_count++;
    m_reader_recursion[thread_id] = 1;
}

void os_rw_lock::acquire_write_lock_internal(std::thread::id thread_id)
{
    m_writer_count++;
    m_current_writer = thread_id;
    m_write_privilege = true;
}

void os_rw_lock::release_read_lock_internal()
{
    m_reader_count--;

    // 如果没有读者了，唤醒等待的写者
    if (m_reader_count == 0 && m_waiting_writers > 0) {
        m_write_privilege = true;
        m_writer_cv.notify_one();
    }
}

void os_rw_lock::release_write_lock_internal()
{
    m_writer_count--;
    m_write_privilege = false;
    m_current_writer = std::thread::id();

    // 优先唤醒等待的写者（写者优先策略）
    if (m_waiting_writers > 0) {
        m_write_privilege = true;
        m_writer_cv.notify_one();
    } else {
        // 如果没有等待的写者，唤醒所有读者
        m_reader_cv.notify_all();
    }
}

// 读锁操作
void os_rw_lock::read_lock()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    std::thread::id this_id = std::this_thread::get_id();

    // 检查是否已经持有读锁（可重入）
    auto it = m_reader_recursion.find(this_id);
    if (it != m_reader_recursion.end()) {
        it->second++;
        return;
    }

    // 使用条件变量避免虚假唤醒
    m_reader_cv.wait(lock, [this]() {
        return can_acquire_read_lock();
    });

    acquire_read_lock_internal(this_id);
}

bool os_rw_lock::try_read_lock()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    std::thread::id this_id = std::this_thread::get_id();

    // 检查重入
    auto it = m_reader_recursion.find(this_id);
    if (it != m_reader_recursion.end()) {
        it->second++;
        return true;
    }

    // 检查是否可以立即获取读锁
    if (can_acquire_read_lock()) {
        acquire_read_lock_internal(this_id);
        return true;
    }

    return false;
}

void os_rw_lock::read_unlock()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    std::thread::id this_id = std::this_thread::get_id();

    auto it = m_reader_recursion.find(this_id);
    if (it == m_reader_recursion.end()) {
        throw std::runtime_error("Thread does not hold read lock");
    }

    // 减少重入计数
    if (--it->second == 0) {
        m_reader_recursion.erase(it);
        release_read_lock_internal();
    }
}

// 写锁操作
void os_rw_lock::write_lock()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    std::thread::id this_id = std::this_thread::get_id();

    // 检查是否已经持有写锁（可重入）
    if (m_writer_count > 0 && m_current_writer == this_id) {
        m_writer_count++;
        return;
    }

    m_waiting_writers++;

    // 使用条件变量避免虚假唤醒
    m_writer_cv.wait(lock, [this]() {
        return can_acquire_write_lock();
    });

    m_waiting_writers--;
    acquire_write_lock_internal(this_id);
}

bool os_rw_lock::try_write_lock()
{
    std::unique_lock<std::mutex> lock(m_mutex);
    std::thread::id this_id = std::this_thread::get_id();

    // 检查重入
    if (m_writer_count > 0 && m_current_writer == this_id) {
        m_writer_count++;
        return true;
    }

    // 检查是否可以立即获取写锁
    if (can_acquire_write_lock()) {
        acquire_write_lock_internal(this_id);
        return true;
    }

    return false;
}

void os_rw_lock::write_unlock()
{
    std::unique_lock<std::mutex> lock(m_mutex);

    if (m_writer_count == 0) {
        throw std::runtime_error("No active writer to unlock");
    }

    if (--m_writer_count == 0) {
        release_write_lock_internal();
    }
}

// 状态查询
int os_rw_lock::get_reader_count() const
{
    std::unique_lock<std::mutex> lock(m_mutex);
    return m_reader_count;
}

int os_rw_lock::get_writer_count() const
{
    std::unique_lock<std::mutex> lock(m_mutex);
    return m_writer_count;
}

int os_rw_lock::get_waiting_writers_count() const
{
    std::unique_lock<std::mutex> lock(m_mutex);
    return m_waiting_writers;
}

bool os_rw_lock::is_write_privilege_granted() const
{
    std::unique_lock<std::mutex> lock(m_mutex);
    return m_write_privilege;
}

bool os_rw_lock::is_current_reader() const
{
    std::unique_lock<std::mutex> lock(m_mutex);
    return m_reader_recursion.count(std::this_thread::get_id()) > 0;
}

bool os_rw_lock::is_current_writer() const
{
    std::unique_lock<std::mutex> lock(m_mutex);
    return m_current_writer == std::this_thread::get_id();
}

// RAII 包装器实现
os_rw_lock::read_guard::read_guard(os_rw_lock& lock) :
    m_rw_lock(lock)
{
    m_rw_lock.read_lock();
}

os_rw_lock::read_guard::~read_guard()
{
    m_rw_lock.read_unlock();
}

os_rw_lock::write_guard::write_guard(os_rw_lock& lock) :
    m_rw_lock(lock)
{
    m_rw_lock.write_lock();
}

os_rw_lock::write_guard::~write_guard()
{
    m_rw_lock.write_unlock();
}